/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007-2008 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.security.ws.server;

import java.util.Map;

import org.apache.cxf.binding.soap.SoapFault;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor;
import org.apache.ws.security.WSSecurityException;

/**
 * WSS4JInHandler subclass that can be configured to ignore (swallow) faults.
 * <p>
 * This might be useful if you need a standard e.g. Spring configuration for all
 * your services, which always sets up the WSS4JInHandler etc. because in that
 * case a WSS Header now *HAS* to be present (even if the service provider is
 * not actually interested and using e.g. Spring Security to retrieve uid), else
 * a SoapFault with code NO_SECURITY occurs.
 * </p>
 * With this Handler, if there is a WSS Header the Spring Security Context gets
 * set, but if there is none, the Spring Security Context is simply null.
 */
public class ForgivingWSS4jInInterceptor
    extends WSS4JInInterceptor
{

  /**
   * the error code to ignore.
   */
  private int errorCodeToIgnore = -1;



  /**
   * Constructor, simply delegates to superclass.
   */
  public ForgivingWSS4jInInterceptor()
  {
    super();
  }



  /**
   * Constructor, simply delegates to superclass.
   * 
   * @param properties
   *          the properties used to configure the handler
   */
  public ForgivingWSS4jInInterceptor(Map<String, Object> properties)
  {
    super(properties);
  }



  /**
   * delegate the handling to the parent and then silently ignore exception that
   * must be accepted.
   * 
   * @param msg
   *          the message being processed
   * @throws Fault
   *           if an error occured
   * @see org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor#handleMessage(org.apache.cxf.binding.soap.SoapMessage)
   */
  @Override
  public void handleMessage(SoapMessage msg)
      throws Fault
  {
    try {
      super.handleMessage(msg);
    }
    catch (SoapFault exception) {
      // We check the cause of the exception, because the exception of interest if wrapped in a SoapFault.
      Throwable cause = exception.getCause();
      // If the cause if a WSSecurityException, that could be the element of interest.
      if (cause != null && cause instanceof WSSecurityException) {
        // We check if the error code is the one to ignore.
        if (errorCodeToIgnore == ((WSSecurityException) cause).getErrorCode()) {
          // then silently ignore this
          msg.put(ForgivingWSS4jInInterceptor.class.getName(), Boolean.TRUE);
          return;
        }
      }
      // else re-throw
      throw exception;

    }
  }



  /**
   * getter for the errorCodeToIgnore property.
   * 
   * @return the errorCodeToIgnore
   */
  public int getErrorCodeToIgnore()
  {
    return errorCodeToIgnore;
  }



  /**
   * setter for the errorCodeToIgnore property.
   * 
   * @param errorCodeToIgnore
   *          the errorCodeToIgnore to set
   */
  public void setErrorCodeToIgnore(int errorCodeToIgnore)
  {
    this.errorCodeToIgnore = errorCodeToIgnore;
  }

}
